package com.example.springboot3demo.config;

import com.example.springboot3demo.config.interceptor.RequestLoggingInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.*;

import java.util.List;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    /**
     * 配置消息转换器
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 添加 Jackson 转换器
        converters.add(new MappingJackson2HttpMessageConverter());
    }

    /**
     * 配置跨域支持
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*") // 允许所有域名进行跨域调用
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的请求方法
                .allowedHeaders("*") // 允许任何请求头
//                .allowCredentials(true) // 允许携带凭证
                .maxAge(3600); // 预检请求的缓存时间（秒）
    }

    /**
     * 跨域过滤器（另一种配置方式）
     */
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOriginPattern("*"); // 支持 Spring Boot 2.4+，替代 allowedOrigins("*")
        config.setAllowCredentials(true);
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        return new CorsFilter(source);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 1. 优先映射Knife4j官方资源
        registry.addResourceHandler("doc.html", "swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/favicon.ico")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");

        // 2. 再映射自定义静态资源（避免覆盖前面的规则）
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/");

        // 3. 若需要自定义doc.html，确保路径不冲突
        registry.addResourceHandler("/custom-doc.html")
                .addResourceLocations("classpath:/templates/");

        // 简化的调试输出
        System.out.println("\n=== 注册的资源处理器 ===");
        System.out.println("registry: " + registry);
        System.out.println("=======================\n");
    }

    /**
     * 添加拦截器（使用推荐的 HandlerInterceptor 接口）
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new RequestLoggingInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/static/**", "/login");
    }

    /**
     * 配置视图控制器（简化请求-视图映射）
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index"); // 根路径映射到 index 视图
        registry.addViewController("/login").setViewName("login"); // 登录页面
    }

    /**
     * 配置路径匹配选项
     */
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 关闭后缀模式匹配（如 /user 不会匹配 /user.json）
        configurer.setUseSuffixPatternMatch(false);
    }

    /**
     * 配置内容协商选项
     */
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        // 基于请求头的内容协商（不使用 URL 后缀）
        configurer.favorParameter(false)
                .favorPathExtension(false)
                .ignoreAcceptHeader(false)
                .defaultContentType(org.springframework.http.MediaType.APPLICATION_JSON);
    }
}